#include "cps1848.h"

unsigned int initIIC( unsigned int iicSclkRate )
{
	int Status;
	XIicPs_Config *Config;

	/*
	 * Initialize the IIC driver so that it's ready to use
	 * Look up the configuration in the config table,
	 * then initialize it.
	 */
	Config = XIicPs_LookupConfig(IIC_DEVICE_ID);
	if (NULL == Config) {
		return XST_FAILURE;
	}

	Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Perform a self-test to ensure that the hardware was built correctly.
	 */
	Status = XIicPs_SelfTest(&Iic);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	// Set the IIC serial clock rate.
	XIicPs_SetSClk(&Iic, iicSclkRate);	//IIC_SCLK_RATE
	// Set the IIC options.
	XIicPs_SetOptions(&Iic, XIICPS_7_BIT_ADDR_OPTION );

	return XST_SUCCESS;
}


unsigned int initTimer( void )
{
	int Status;
	u32 Register;

	XScuTimer_Config *ConfigPtr;
	XScuTimer *TimerInstancePtr = &Timer;

	/*
	 * Initialize the Scu Private Timer so that it is ready to use.
	 */
	ConfigPtr = XScuTimer_LookupConfig(XPAR_XSCUTIMER_0_DEVICE_ID);

	/*
	 * This is where the virtual address would be used, this example
	 * uses physical address.
	 */
	Status = XScuTimer_CfgInitialize(TimerInstancePtr, ConfigPtr, ConfigPtr->BaseAddr);
	if (Status != XST_SUCCESS) 
	{
		return XST_FAILURE;
	}

	/*
	 * Load the timer counter register.
	 */
	XScuTimer_LoadTimer(TimerInstancePtr, SCU_TIMER_AUTO_LOAD_INIT_VAL);

	// set Auto-load mode
 	Register = XScuTimer_ReadReg(TimerInstancePtr->Config.BaseAddr, XSCUTIMER_CONTROL_OFFSET);
	Register |= XSCUTIMER_CONTROL_AUTO_RELOAD_MASK;
	XScuTimer_WriteReg(TimerInstancePtr->Config.BaseAddr, XSCUTIMER_CONTROL_OFFSET, Register);

	/*
	 * Start the Scu Private Timer device.
	 */
	XScuTimer_Start(TimerInstancePtr);

	return XST_SUCCESS;
}

unsigned int IICReadReg( unsigned int devID, unsigned int offset, unsigned int *readdata )
{
	unsigned int Status;
	unsigned int tmpU32;

	unsigned int rc = 0;
	IIC_DATA iicData;

	iicData.adrs = offset>>2;
	tmpU32 = iicData.adrs;
	iicData.adrs = ((tmpU32>>24)&0xFF) | ((tmpU32>>8)&0xFF00) | ((tmpU32<<8)&0xFF0000) | ((tmpU32<<24)&0xFF000000);

	if( HOST_REGS_DEVID == devID )
	{
		;
	}
	else
	{
		Status = XIicPs_MasterSendPolled(&Iic, ((unsigned char*)&iicData+1), 3, devID);
		if (Status != XST_SUCCESS) 
		{
			rc = XST_FAILURE;
		}
		
		/* Wait until bus is idle to start another transfer.	 */
		while (XIicPs_BusIsBusy(&Iic));

		Status = XIicPs_MasterRecvPolled(&Iic, (unsigned char*)readdata, 4, devID);
		if (Status != XST_SUCCESS) 
		{
			rc = XST_FAILURE;
		}
		
		/* Wait until bus is idle to start another transfer.	 */		
		while (XIicPs_BusIsBusy(&Iic));
		
		tmpU32 = *readdata;
		*readdata = ((tmpU32>>24)&0xFF) | ((tmpU32>>8)&0xFF00) | ((tmpU32<<8)&0xFF0000) | ((tmpU32<<24)&0xFF000000);
	}

	return rc;
}


unsigned int IICWriteReg( unsigned int devID, unsigned int offset, unsigned int  writedata )
{
	int Status;
	unsigned int tmpU32;

	unsigned int rc = 0;
	IIC_DATA iicData;


	iicData.adrs = offset>>2;
	iicData.data = writedata;
	

	tmpU32 = iicData.adrs;
	iicData.adrs = ((tmpU32>>24)&0xFF) | ((tmpU32>>8)&0xFF00) | ((tmpU32<<8)&0xFF0000) | ((tmpU32<<24)&0xFF000000);

	tmpU32 = iicData.data;
	iicData.data = ((tmpU32>>24)&0xFF) | ((tmpU32>>8)&0xFF00) | ((tmpU32<<8)&0xFF0000) | ((tmpU32<<24)&0xFF000000);

	if( HOST_REGS_DEVID == devID )
	{
		;
	}
	else
	{
		Status = XIicPs_MasterSendPolled(&Iic, ((unsigned char*)&iicData+1), 7, devID);
		if (Status != XST_SUCCESS) 
		{
			rc = XST_FAILURE;
		}
		
		/* Wait until bus is idle to start another transfer.	 */
		while (XIicPs_BusIsBusy(&Iic));
	}

	return rc;
}


int IIC1848Init( unsigned int iicDeviceAdrs, unsigned int iicSclkRate )
{
	unsigned int _data;

	initTimer();
	initIIC(iicSclkRate);

	IICReadReg(iicDeviceAdrs,0,&_data);

	if( _data == DEVICE_ID_1848 )
		return 0;
	else
		return 1;
}
